<?php
/**
 * Created by PhpStorm.
 * User: ZhangYinxian
 * Date: 2016-10-05
 * Time: 20:30
 */

namespace app\index\logic;
use think\Db;
/**
 * 纯化难度预测及方法
 * Class PurifyDifficult
 * @package app\index\logic
 */
class PurifyDifficult extends AminoSubject
{
    private $mCode = 0;

    public function getResult(){
        $result = parent::getResult();
        $this->calculateSpecialSequences();

        $purify_difficult_data = Db::table('amino_purify')->where('code', $this->mCode)->find();
        $message = '暂时无纯化难度预测结果';
        if(!is_null($purify_difficult_data)){
             $result['purify_difficult_data']=$purify_difficult_data;
        }else{
             $result['has_error'] = true;
             $result['message']=$message;
        }
        return $result;
     }

    /**
     * 计算含特殊字符串序列的特性
     */
     private function calculateSpecialSequences(){
         // 条件1 RADA\TSTS\IKIE\QQQQ\NNNNN\DSSDSS等循化序列，循环2次以上
         $subject = $this->mAminoSubject;
         $special_residuces = ['RADA','TSTS','IKIE','QQQQ','NNNNN','DSSDSS'];
         foreach ($special_residuces as $special_residuce){
             $result = preg_match_all("/($special_residuce)/", $subject);
             if($result>=2){
                 return $this->setCode(300);
             }
         }

         // 条件2 长度大于10个且Q、S、T、Y残基比例≥40%
         $amino_count =$this->mAminoSubject->mAminoCount;
         if($amino_count>=10){
             $amino_detials = $this->mAminoSubject->mAminoDetails;

             $tmp_count = 0;
             foreach ($amino_detials as $amino_detial ){
                 $single = $amino_detial['detail']['single'];
                 switch ($single){
                     case 'Q':
                     case 'S':
                     case 'T':
                     case 'Y':
                         $tmp_count += $amino_detial['count'];
                         break;
                 }
             }
             if($tmp_count / $amino_count >= 0.4){
                 return $this->setCode(301);
             }
         }

         $purify = $this->mAminoSubject->mPurify;
         $purify_max_count = $this->calculateColumnMaxCount('purify', 0, ['Ac','NH2']);
         //条件3 0＜疏水值≤0.5且有8个及以上连续氨基酸的疏水性≤0
         if ($purify>0 && $purify<=0.5 && $purify_max_count>=8){
             return $this->setCode(302);
         }

         //条件4 -1<疏水值≤0且有6个及以上连续氨基酸的疏水性≤0
         if($purify>-1 && $purify<=0 && $purify_max_count>=6){
             return $this->setCode(303);
         }

         $amino_locations = $this->mAminoSubject->mAminoLocation;
         $standard_data = $this->mChemicalData['standard_data'];
         $cyclo_enable_count = 0;
         foreach($amino_locations as $chain_amino_location){
             if(count($chain_amino_location)>0){
                 foreach ($chain_amino_location as $amino_location){
                     $single = $amino_location['single'];
                     $data = isset($standard_data[$single])? $standard_data[$single] : null;
                     if (is_null($data)) continue;
                     if ($data['cyclo_enable']==2) $cyclo_enable_count++;
                 }
             }
         }

         if ($cyclo_enable_count>=4 && $cyclo_enable_count<6){
             return $this->setCode(304);
         }
         if ($cyclo_enable_count>=6){
             return $this->setCode(400);
         }


         $mw = $this->mAminoSubject->mMw;
         // 条件5 分子量≤500, 疏水性＞2.5
         // 条件6 分子量≤500, 2.5≥疏水性＞-0.5, 酸、碱个数均为0
         // 条件7 分子量≤500, 2.5≥疏水性＞-0.5, 碱个数=0，酸个数>0, 含有base_unstable为2的氨基酸总个数≥2，或base_unstable为1的氨基酸的总个数>0
         // 条件8 分子量≤500, 2.5≥疏水性＞-0.5, 碱个数=0，酸个数>0, 其它情况
         // 条件8 分子量≤500, 2.5≥疏水性＞-0.5, 其它情况
         if ($mw<=500){
             // 条件5
              if ($purify>2.5){
                  return $this->setCode(100);
              }

             $acid_count = $this->mAminoSubject->mAcidCount;
             $base_count = $this->mAminoSubject->mBaseCount;

              if ($purify<=2.5 && $purify>-0.5){

                  // 条件6
                  if($acid_count==0 && $base_count==0){
                       return $this->setCode(101);
                  }
                  // 条件7
                  if ($base_count==0 && $acid_count>0){
                      return $this->baseUnstableResult(200, 102);
                  }

                  return $this->setCode(1);
              }

              // 条件10-13
             if ($purify<=-0.5 && $purify>-1.2){
                 // 条件10
                 if($acid_count==0 && $base_count==0){
                     return $this->setCode(201);
                 }

                 if (($acid_count-$base_count)>=1){
                     return $this->baseUnstableResult(305,202);
                 }

                 return $this->setCode(103);
             }

             // 条件15-18
             if ($purify<=-1.2 && $purify>-2.0){
                 if($acid_count==0 && $base_count==0){
                     return $this->setCode(306);
                 }

                 if (($acid_count-$base_count)>=1){
                     return $this->baseUnstableResult(307,308);
                 }

                 return $this->setCode(203);
             }

             if ($purify<=-2.0){
                 return $this->setCode(401);
             }
         }

         // mw>500的, 条件19-35
         $mw_value = 0.2*$mw / 1000;
         $mw_value = ($mw_value<0.7) ? $mw_value : 0.7;

         $acid_count = $this->mAminoSubject->mAcidCount;
         $base_count = $this->mAminoSubject->mBaseCount;

         $base_acid_all_percent = ($acid_count+$base_count)/$amino_count;
         $acid_base_percent = ($acid_count-$base_count)/$amino_count;
         $base_acid_percent = ($base_count - $acid_count) / $amino_count;

         $amino_type_count = $this->getAminoTypeCount();

         if ($purify> (-0.5+$mw_value)){

             if ( $base_acid_all_percent >= 0.3){
                 return $this->setCode(2);
             }

             if ($base_acid_all_percent<0.3 && $acid_base_percent>=0.1){
                 return $this->baseUnstableResult(204, 104);
             }

             if ($base_acid_all_percent<0.3 && $acid_base_percent>0 && $acid_base_percent<0.1){
                 return $this->setCode(205);
             }

             if ($base_acid_all_percent<0.3 && $acid_base_percent<=0){
                 return $this->setCode(105);
             }
         }

         if ($purify<=(-0.5+$mw_value) && $purify>(-1.1+$mw_value)){
             if ($base_acid_all_percent>=0.35){

                 if ($acid_base_percent>=0.1){
                     return $this->setCode(206);
                 }
                 if ($base_acid_percent>=0.1){
                     return $this->setCode(106);
                 }

                 return $this->setCode(107);
             }

             if ($base_acid_all_percent<0.35 && $acid_base_percent>=0.1){
                 return $this->baseUnstableResult(309, 207);
             }

             if ($base_acid_all_percent<0.35 && $acid_base_percent>0 && $acid_base_percent<=0.1 && $amino_type_count>=2){
                 return $this->baseUnstableResult(310, 311);
             }

             if ($base_acid_all_percent<0.35 && $acid_base_percent>0 && $acid_base_percent<=0.1){
                 return $this->setCode(312);
             }

             if ($base_acid_all_percent<0.35 && $acid_base_percent<0){
                 return $this->setCode(208);
             }
         }

         if ($purify<=(-1.1+$mw_value) && $purify>(-1.5+$mw_value)) {
             if ($base_acid_all_percent>=0.35){

                 if ($acid_base_percent>=0.1){
                     return $this->setCode(313);
                 }

                 return $this->setCode(209);
             }

             if ($base_acid_all_percent<0.35 && $acid_base_percent>=0.1){
                 return $this->baseUnstableResult(314,315);
             }

             if ($base_acid_all_percent<0.35 && $acid_base_percent>0 && $acid_base_percent<=0.1 && $amino_type_count>=2){
                 return $this->baseUnstableResult(316,317);
             }

             if ($base_acid_all_percent<0.35 && $acid_base_percent>0 && $acid_base_percent<=0.1){
                 return $this->setCode(318);
             }

             if ($base_acid_all_percent<0.35 && $acid_base_percent<0){
                 return $this->setCode(319);
             }
         }

         return $this->setCode(402);

     }

     private function setCode($code){
         $this->mCode = $code;
      }

    /**
     * 碱稳定条件设置
     * @param $trueValue int true  返回的值
     * @param $falseValue int false 返回的值
     */
      private function baseUnstableResult($trueValue, $falseValue){
          $base_unstable2 = $this->getStandardDataColumnCount(2);
          $base_unstable1 = $this->getStandardDataColumnCount(1);
          if ($base_unstable2>=2 || $base_unstable1>0){
              return $this->setCode($trueValue);
          }else{
              return $this->setCode($falseValue);
          }
      }

    /**
     * 获取amino_type=1的数量
     */
      private function getAminoTypeCount($aminoType=1){
          $amino_type_count = 0;
          $amino_details = $this->mAminoSubject->mAminoDetails;
          $amino_pi_data = $this->mChemicalData['pi_data'];
          foreach ($amino_details as $amino_detail){
              $single = $amino_detail['detail']['single'];
              if (isset($amino_pi_data[$single])){
                  $amino_pi = $amino_pi_data[$single];
                  $amino_type = $amino_pi['amino_type'];
                  $amino_ratio = $amino_pi['ratio'];
                  if ($amino_type==$aminoType){
                      $amino_type_count += $amino_detail['count']*$amino_ratio;
                  }
              }
          }

          return $amino_type_count;
      }
    /**
     * 获取指定列的某一个值的总数
     * @param $defaultValue int 默认值
     * @param $columnName string 列名
     * @return int 总数
     */
      private function getStandardDataColumnCount($defaultValue, $columnName='base_unstable'){
          $base_unstable_count = 0;
          $amino_details = $this->mAminoSubject->mAminoDetails;
          $standard_data = $this->mChemicalData['standard_data'];
          foreach($amino_details as $amino_detail){
              if (isset($standard_data[$amino_detail['detail']['single']])){
                  $base_unstable = $standard_data[$amino_detail['detail']['single']][$columnName];
                  if ($base_unstable==$defaultValue){
                      $base_unstable_count += $amino_detail['count'];
                  }
              }
          }
          return $base_unstable_count;
      }
}